namespace SubSonic
{
    using SubSonic.Utilities;
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Common;

    public class QueryCommand
    {
        private DataProvider _provider;
        private string _providerName;
        private string commandSql;
        private int commandTimeout;
        private System.Data.CommandType commandType;
        public List<object> OutputValues;
        private QueryParameterCollection parameters;

        public QueryCommand(string sql)
        {
            this.commandTimeout = 60;
            this._providerName = string.Empty;
            this.ProviderName = DataService.Provider.Name;
            this.Provider = DataService.Provider;
            this.commandSql = sql;
            this.CommandType = System.Data.CommandType.Text;
            this.parameters = new QueryParameterCollection();
            this.OutputValues = new List<object>();
        }

        public QueryCommand(string sql, string providerName)
        {
            this.commandTimeout = 60;
            this._providerName = string.Empty;
            this.ProviderName = providerName;
            this.Provider = DataService.GetInstance(providerName);
            this.commandSql = sql;
            this.CommandType = System.Data.CommandType.Text;
            this.parameters = new QueryParameterCollection();
            this.OutputValues = new List<object>();
        }

        public void AddOutputParameter(string parameterName)
        {
            this.AddOutputParameter(parameterName, -1, DbType.AnsiString);
        }

        public void AddOutputParameter(string parameterName, DbType dbType)
        {
            this.AddOutputParameter(parameterName, -1, dbType);
        }

        public void AddOutputParameter(string parameterName, int maxSize)
        {
            this.AddOutputParameter(parameterName, maxSize, DbType.AnsiString);
        }

        public void AddOutputParameter(string parameterName, int maxSize, DbType dbType)
        {
            this.AddParameter(parameterName, DBNull.Value, maxSize, dbType, ParameterDirection.Output);
        }

        public void AddParameter(string parameterName, object parameterValue)
        {
            this.AddParameter(parameterName, parameterValue, DbType.AnsiString);
        }

        public void AddParameter(string parameterName, object parameterValue, DbType dataType)
        {
            this.AddParameter(parameterName, parameterValue, 50, dataType, ParameterDirection.Input);
        }

        public void AddParameter(string parameterName, object parameterValue, DbType dataType, ParameterDirection parameterDirection)
        {
            this.AddParameter(parameterName, parameterValue, 50, dataType, parameterDirection);
        }

        private void AddParameter(string parameterName, object parameterValue, int maxSize, DbType dbType, ParameterDirection direction)
        {
            if (this.parameters == null)
            {
                this.parameters = new QueryParameterCollection();
            }
            QueryParameter item = new QueryParameter();
            item.ParameterName = Utility.PrefixParameter(parameterName, this.Provider);
            item.ParameterValue = parameterValue ?? DBNull.Value;
            item.Mode = direction;
            item.DataType = dbType;
            if (maxSize > -1)
            {
                item.Size = maxSize;
            }
            this.parameters.Add(item);
        }

        public void AddReturnParameter()
        {
            this.AddParameter("@RETURN_VALUE", null, DbType.Int32, ParameterDirection.ReturnValue);
        }

        public bool HasOutputParams()
        {
            foreach (QueryParameter parameter in this.Parameters)
            {
                if (((parameter.Mode == ParameterDirection.InputOutput) || (parameter.Mode == ParameterDirection.Output)) || (parameter.Mode == ParameterDirection.ReturnValue))
                {
                    return true;
                }
            }
            return false;
        }

        public DbCommand ToDbCommand()
        {
            return DataService.GetDbCommand(this);
        }

        public IDbCommand ToIDbCommand()
        {
            return DataService.GetIDbCommand(this);
        }

        public string CommandSql
        {
            get
            {
                return this.commandSql;
            }
            set
            {
                this.commandSql = value;
            }
        }

        public int CommandTimeout
        {
            get
            {
                return this.commandTimeout;
            }
            set
            {
                this.commandTimeout = value;
            }
        }

        public System.Data.CommandType CommandType
        {
            get
            {
                return this.commandType;
            }
            set
            {
                this.commandType = value;
            }
        }

        public QueryParameterCollection Parameters
        {
            get
            {
                return this.parameters;
            }
            set
            {
                this.parameters = value;
            }
        }

        public DataProvider Provider
        {
            get
            {
                return this._provider;
            }
            set
            {
                this._provider = value;
            }
        }

        public string ProviderName
        {
            get
            {
                return this._providerName;
            }
            set
            {
                this._providerName = value;
            }
        }
    }
}

